﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfDrawing
{
    /// <summary>
    /// BarChartControl.xaml 的交互逻辑
    /// </summary>
    public partial class BarChartControl : UserControl
    {


        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(BarChartControl), new PropertyMetadata(""));





        public int MaxValue
        {
            get { return (int)GetValue(MaxValueProperty); }
            set { 
                SetValue(MaxValueProperty, value);
                this.InvalidateVisual();

            }
        }

        // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxValueProperty =
            DependencyProperty.Register("MaxValue", typeof(int), typeof(BarChartControl), 
                new FrameworkPropertyMetadata(250,new PropertyChangedCallback(MaxValueChangedCallback) ));

        public static void MaxValueChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as BarChartControl).MaxValue = (int)e.NewValue;
            (sender as BarChartControl).UpdateKD();
        }



        public IEnumerable<object> ItemSource
        {
            get { return (IEnumerable<object>)GetValue(ItemSourceProperty); }
            set { SetValue(ItemSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemSourceProperty =
            DependencyProperty.Register("ItemSource", typeof(IEnumerable<object>), typeof(BarChartControl),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(ItemSourceChangedCallback)));


        public static void ItemSourceChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as BarChartControl).DrawXsegment();
        }




        public string DisplayMemberMsg
        {
            get { return (string)GetValue(DisplayMemberMsgProperty); }
            set { SetValue(DisplayMemberMsgProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberMsg.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberMsgProperty =
            DependencyProperty.Register("DisplayMemberMsg", typeof(string), typeof(BarChartControl), new PropertyMetadata("Name"));




        public string DisplayMemberValue
        {
            get { return (string)GetValue(DisplayMemberValueProperty); }
            set { SetValue(DisplayMemberValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberValueProperty =
            DependencyProperty.Register("DisplayMemberValue", typeof(string), typeof(BarChartControl), new PropertyMetadata("Value"));





        public BarChartControl()
        {
            InitializeComponent();
            DrawYSegment();

            //DrawXsegment();//不能放再这里，里面用到了MaxValue。这个值在XAML中赋值了，但在构造函数中还没有值，在load中才有值
            
        }


        private Point StartPoint = new Point(100, 300);
        private int xWidth = 600;
        private int xSegmentCount = 7;


        private int yHeight = 250;
        private int ySegmentCount = 25; //Y轴的总刻度分段， 
        private int SingleYSegmentLentgh//Y轴刻度线间隔
        {
            get { return yHeight / ySegmentCount; }
        }
        private int SingleYSegmentValue//Y轴刻度线单位值
        {
            get
            {
                return  MaxValue / ySegmentCount;
            }
        }


        private int InnerLineWdith=10;


        /// <summary>
        /// 画Y轴的刻度线
        /// </summary>
        private void  DrawYSegment()
        {
            //纵轴坐标，从下往上，(100,300) -> (100,50) 总长 250,分成25段。每段长10。
            //类推，从下往上，坐标。依次为 [(95,300)(105,300)][(95,290)(105,290)]......

            double StartPointX = StartPoint.X;
            double x1 = StartPointX - InnerLineWdith / 2;
            double x2 = StartPointX;


            double PointY = StartPoint.Y;
            

            for (int i=0;i<= ySegmentCount;i++)
            {
                int l = 0;
                if((i ) % 5 == 0)//逢5 画 刻度的值，且刻度线长度+5
                {
                    l = 5;
                    //< Label Width = "60"  VerticalContentAlignment = "Center" HorizontalContentAlignment = "Right" 
                    // Height = "30"  Margin = "20,245,0,0" HorizontalAlignment = "Left" > 50 </ Label >
                    Label label = new Label()
                    {
                        Width=60,
                        VerticalContentAlignment =  VerticalAlignment.Center,
                        HorizontalContentAlignment =  HorizontalAlignment.Right,
                        Height=30,
                        //Content= SingleYSegmentValue*(i)
                    };
                    Ylbls.Add(label);
                    double x = StartPointX -(InnerLineWdith / 2)-60 - 20;  //x坐标值=StartPointX-（InnerLineWdith / 2）-label宽度 -20
                    double y = PointY - 30 / 2;//label y坐标
                    Canvas.SetTop(label,y);
                    Canvas.SetLeft(label,x);
                    canvas.Children.Add(label);

                }

                Point p1 = new Point(x1 - l, PointY);
                Point p2 = new Point(x2, PointY);
                AddYSingleLine(p1, p2);
                PointY -= SingleYSegmentLentgh;
            }


        }
        private List<Label> Ylbls = new List<Label>();
        public void  UpdateKD()
        {
            var footer = SingleYSegmentValue * 5;
            foreach (var item in Ylbls)
            {
                item.Content = Ylbls.IndexOf(item) * footer;
            }
        }

        private void AddYSingleLine(Point p1,Point p2)
        {
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = p1;
            pathFigure.Segments.Add(new LineSegment(p2, true));
            Yline.Figures.Add(pathFigure);
        }



        private object GetValueFromObject(object obj,string propName)
        {
            Type type = obj.GetType();

            PropertyInfo property= type.GetProperty(propName);

            return property.GetValue(obj);

        }


        private void DrawXsegment()
        {
            if(ItemSource==null)
            {
                return;
            }

            //横轴坐标，70长度为一段，
            double StartPointX= StartPoint.X;
            double PointY1 = StartPoint.Y;
            double PointY2 = StartPoint.Y + 10;

            //为支持重复跟新，需要支持重复画
            {
                xline.Figures.Clear();
                barGP.Children.Clear();
                foreach (var lbl in lstLabel)
                {
                    canvas.Children.Remove(lbl);
                }
                
            }

            

            foreach (var item in ItemSource)
            {

                try
                {
                    Point p1 = new Point(StartPointX, PointY1);
                    Point p2 = new Point(StartPointX, PointY2);
                    AddXSingleLine(p1, p2);
                    StartPointX += 70;//间隔为70

                    //bar的宽度为30，那么bar左右间隔为20,bar的右下角坐标为StartPointX-20 ,PointY1. 
                    //那么 左上角坐标为 StartPointX-20 -30,PointY1-barheight;



                    //这里用了反射，其实用binding来做才是合理的，这样当 ItemSource里的值改变时，界面才会响应改变
                    //怎么用绑定实现待完成，应该去参考listbox中 .DisplayMemberPath的绑定方式
                    double value = (double)GetValueFromObject(item, DisplayMemberValue);
                    double barheight = value / SingleYSegmentValue * SingleYSegmentLentgh;//总长度yHeight
                    barGP.Children.Add(new RectangleGeometry(new Rect(StartPointX - 20 - 30, PointY1 - barheight, 30, barheight)));

                    //binding
                    



                    Point P3 = new Point(StartPointX, PointY1);//
                    Label labelBottom = new Label()
                    {
                        Width = 70,
                        VerticalContentAlignment = VerticalAlignment.Bottom,
                        HorizontalContentAlignment = HorizontalAlignment.Center,
                        Height = 40,
                        Content = GetValueFromObject(item, DisplayMemberMsg)
                    };
                    Canvas.SetTop(labelBottom, p1.Y);
                    Canvas.SetLeft(labelBottom, p1.X);
                    canvas.Children.Add(labelBottom);
                    lstLabel.Add(labelBottom);

                    Label labelTop = new Label()
                    {
                        Width = 70,
                        VerticalContentAlignment = VerticalAlignment.Center,
                        HorizontalContentAlignment = HorizontalAlignment.Center,
                        Height = 30,
                        Content = value
                    };
                    Canvas.SetTop(labelTop, PointY1 - barheight - 30);
                    Canvas.SetLeft(labelTop, p1.X);
                    canvas.Children.Add(labelTop);
                    lstLabel.Add(labelTop);
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message);
                }

                
            }

            XMainline.EndPoint = new Point(StartPointX, 300);

            gd.Width = StartPointX + 100;
        }

        private List<Label> lstLabel = new List<Label>();

        private void AddXSingleLine(Point p1, Point p2)
        {
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = p1;
            pathFigure.Segments.Add(new LineSegment(p2, true));
            xline.Figures.Add(pathFigure);
        }



        private void canvas_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateKD();
            DrawXsegment();

        }
    }



    public class BarChartItem
    {
        public string name { get; set; }
        public double money { get; set; }
        public int year { get; set; }
    }
}
